package com.xstar.game.gameoflife;

public class CellGroup {
    // 全部细胞  细胞状态 0 死亡 1 存活
    public final int[][] cells;
    public final int[][] newCells;
    public final int width;
    public final int height;
    public long iterationCount;
    public long nowAliveCellCount;

    public CellGroup(int width, int height) {
        this.width = width;
        this.height = height;
        this.cells = new int[width][height];
        this.newCells = new int[width][height];
    }

    //  迭代细胞群
    public void iteration() {
        update();
        iterationCount++;
    }

    // 处理细胞群内所有单个迭代变化
    private void update() {
        int nowAliveCellCount = 0;

        for (int h = 0; h < height; h++) {
            for (int w = 0; w < width; w++) {
                // 获取单个细胞
                int cell = cells[h][w];

                // 获取此细胞周围存活细胞
                int tl = getCell(w - 1, h - 1);
                int t = getCell(w, h - 1);
                int tr = getCell(w + 1, h - 1);
                int l = getCell(w - 1, h);
                int r = getCell(w + 1, h);
                int bl = getCell(w - 1, h + 1);
                int b = getCell(w, h + 1);
                int br = getCell(w + 1, h + 1);

                int aliveCellCount = tl + t + tr + l + r + bl + b + br;

                // 四种情况处理
                if (aliveCellCount == 3) {
                    // 当前细胞死亡时，附近存活细胞有3个时，此细胞存活（模拟繁衍）
                    setCell(w, h, true);
                } else if (aliveCellCount == 2) {
                    // 当前细胞存活时，附近存活细胞有2个或3个时，保持不变
                    setCell(w, h, cell == 1);
                } else {
                    // 当前细胞存活时，附近存活细胞低于2个，次细胞死亡
                    // 当前细胞存活时，附近存活细胞多于3个，此细胞死亡
                    setCell(w, h, false);
                }

                // 获取本次迭代存活细胞数
                if (newCells[h][w] == 1)
                    nowAliveCellCount++;
            }
        }

        this.nowAliveCellCount = nowAliveCellCount;
        sync();
    }

    private void sync() {
        for (int h = 0; h < height; h++) {
            System.arraycopy(newCells[h], 0, cells[h], 0, width);
        }
    }

    public void setCell(int w, int h, boolean b) {
        if (w >= width || h >= height || w < 0 || h < 0)
            return;

        newCells[h][w] = b ? 1 : 0;
    }

    public int getCell(int w, int h) {
        if (w >= width || h >= height || w < 0 || h < 0)
            return 0;

        return cells[h][w];
    }
}
